package com.atwisdom.star.service.business;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.atwisdom.star.common.util.JsonUtil;
import com.atwisdom.star.common.util.SpringContextUtil;
import com.atwisdom.star.core.dao.pojo.modelClass.hier.HierInstance;
import com.atwisdom.star.core.dao.pojo.modelClass.hier.HierModel;
import com.atwisdom.star.core.dao.pojo.modelClass.twins.TwinsInstance;
import com.atwisdom.star.core.dsl.modelClass.logic.Impl.LogicInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.twins.Impl.TwinsInstanceDslServiceImpl;
import com.atwisdom.star.exception.pojo.BusinessException;
import com.atwisdom.star.service.pojo.BasicStatus;
import com.atwisdom.star.service.status.WorkUnitStatus;
import lombok.Data;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Data
public class WorkUnit extends Business{
    private final TwinsInstanceDslServiceImpl workUnitService = SpringContextUtil.getBean(TwinsInstanceDslServiceImpl.class);
    private final LogicInstanceDslServiceImpl workNoticeService  = SpringContextUtil.getBean(LogicInstanceDslServiceImpl.class);

    private TwinsInstance workUnit;
    private JSONObject workUnitJson;
    private WorkCenter workCenter;
    private List<JSONObject> workNotices;

    private final String workNoticeName = "工单";
    private final String workCenterName = "workCenterId";

    private final String workUnitModel = "twins";
    private final String workUnitType = "workUnit";

    /**
     * 更新工位状态
     * @param id 实例id
     * @param status 状态
     */
    public void updateWorkUnitStatus(Long id,String status){
        WorkUnitStatus workUnitStatus = new WorkUnitStatus(id);
        workUnitStatus.setUpdateStatus(workUnitStatus.getStatusKey(),status);
        workUnitStatus.next();
    }

    /**
     * 回退工位状态
     * @param id 实例id
     * @param status 状态
     */
    public void updateOrderStatusBack(Long id,String status){
        WorkUnitStatus workUnitStatus = new WorkUnitStatus(id);
        workUnitStatus.setUpdateStatus(workUnitStatus.getStatusKey(),status);
        workUnitStatus.back();
    }

    /**
     * 根据名称获取父级id
     * @param name 父级名称
     * @return
     */
    private String getParentIdByName(String name){
        List<HierModel> hierList = workUnit.getHierModels().stream().filter(hierInstance -> name.equals(hierInstance.getName())).collect(Collectors.toList());
        if(CollectionUtil.isEmpty(hierList)){
            throw new BusinessException("父级"+name+"不存在");
        }
        return hierList.get(0).getNodeId();
    }

    /**
     * 获取子级实例
     * @param parentId 父级id
     * @return
     */
    private List<JSONObject> getHierInstances(String parentId) {
        return workUnit.getHierInstances().stream()
                .filter(hierInstance -> parentId.equals(hierInstance.getParentId())&&null!=hierInstance.getLinkId())
                .map(hierInstance -> workNoticeService.queryJsonById(hierInstance.getLinkId()))
                .collect(Collectors.toList());
    }

    /**
     * 获取子级实例
     * @param parentId 父级id
     * @param linkId 链接id
     * @return
     */
    private HierInstance getHierInstance(String parentId,Long linkId) {
        List<HierInstance> hierList = workUnit.getHierInstances().stream()
                .filter(hierInstance -> parentId.equals(hierInstance.getParentId())&&linkId.equals(hierInstance.getLinkId()))
                .collect(Collectors.toList());
        if(CollectionUtil.isEmpty(hierList)){
            throw new BusinessException("子级不存在");
        }else{
            return hierList.get(0);
        }
    }

    /**
     * 初始化工位数据
     * @param id 工位id
     */
    public void setWorkUnit(Long id){
        setWorkUnit(workUnitService.queryInsWithHierById(id));
    }

    /**
     * 初始化工位数据
     * @param workUnit 工位实例
     */
    public void setWorkUnit(TwinsInstance workUnit){
        if(null==workUnit){
            throw new BusinessException("工位不存在");
        }
        this.workUnit = workUnit;
//        setWorkUnitJson(this.workUnit);
        this.workNotices = getHierInstances(getParentIdByName(workNoticeName));
    }

    /**
     * 初始化工位json数据
     * @param workUnit 工位实例
     */
    private void setWorkUnitJson(TwinsInstance workUnit){
        this.workUnitJson = workUnitService.getTwinsInsJsonObjectList(Arrays.asList(workUnit)).get(0);
        this.workCenter = new WorkCenter();
        this.workCenter.setWorkCenter(Long.valueOf(JsonUtil.get(this.workUnitJson,"values."+workCenterName)));
    }

    /**
     * 工单队列增加工单
     * @param workNoticeJson
     */
    public void addWorkNotices(JSONObject workNoticeJson){
        addChild(this.workUnitModel,this.workUnit.getClassName(),this.workUnit.getId(),getParentIdByName(workNoticeName),JsonUtil.buildJson(new Object[]{"linkId",workNoticeJson.getLong("id"),"hierValues",workNoticeJson.getJSONObject("values")}));
        this.workNotices.add(workNoticeJson);
    }

    /**
     * 工单开工
     * @param workNoticeJson
     */
    public void startWorkNotice(JSONObject workNoticeJson){
        if(CollectionUtil.isEmpty(this.workNotices)){
            throw new BusinessException("工单队列为空");
        }
        List<Long> noticeIds = this.workNotices.stream().map(workNotice -> workNotice.getLong("id")).collect(Collectors.toList());
        if(!noticeIds.contains(workNoticeJson.getLong("id"))){
            throw new BusinessException("工单队列中不存在id为："+workNoticeJson.getLong("id")+"的工单");
        }
        JSONObject json = workUnitService.getTwinsInsJsonObjectList(Arrays.asList(workUnit)).get(0);
        if(null!=JsonUtil.get(json,"values.workNoticeId")){
            List<JSONObject> notices = this.workNotices.stream()
                    .filter(workNotice -> (JsonUtil.get(workNotice,"id").equals(JsonUtil.get(json,"values.workNoticeId"))))
                    .collect(Collectors.toList());
            if(CollectionUtil.isNotEmpty(notices)){
                throw new BusinessException("工单有工单正在进行中，工单信息为："+notices.toString()+"，不可开工！");
            }
        }
//        JSONObject values = JsonUtil.buildJson(new Object[]{"workNoticeId",JsonUtil.get(workNoticeJson,"id"),"routingId",JsonUtil.get(workNoticeJson,"values.routingId"),"workCenterId",JsonUtil.get(workNoticeJson,"values.workCenterId"),"status","工作"});
        JSONObject values = JsonUtil.buildJson(new Object[]{"workNoticeId",JsonUtil.get(workNoticeJson,"id"),"routingId",JsonUtil.get(workNoticeJson,"values.routingId"),"workCenterId",JsonUtil.get(workNoticeJson,"values.workCenterId")});
        json.put("values",values);
        workUnitService.updateById(json);
        updateWorkUnitStatus(json.getLong("id"), BasicStatus.WORK_UNIT_STATUS_WORK);
    }

    /**
     * 工单完工
     * @param workNoticeJson
     */
    public void endWorkNotice(JSONObject workNoticeJson) {
        JSONObject json = workUnitService.getTwinsInsJsonObjectList(Arrays.asList(workUnit)).get(0);
        if(CollectionUtil.isEmpty(this.workNotices)){
            throw new BusinessException("工单队列为空");
        }
        List<Long> noticeIds = this.workNotices.stream().map(workNotice -> workNotice.getLong("id")).collect(Collectors.toList());
        if(!noticeIds.contains(workNoticeJson.getLong("id"))){
            throw new BusinessException("工单队列中不存在id为："+workNoticeJson.getLong("id")+"的工单");
        }
        if(!(JsonUtil.get(workNoticeJson,"id").equals(JsonUtil.get(json,"values.workNoticeId"))
                &&JsonUtil.get(workNoticeJson,"values.routingId").equals(JsonUtil.get(json,"values.routingId"))
                &&JsonUtil.get(workNoticeJson,"values.workCenterId").equals(JsonUtil.get(json,"values.workCenterId")))){
            throw new BusinessException("工单信息不匹配");
        }
        HierInstance hierInstance = getHierInstance(getParentIdByName(workNoticeName),workNoticeJson.getLong("id"));
        hierInstanceDslServiceImpl.deleteById(hierInstance.getId());
//        json.put("values",JsonUtil.buildJson(new Object[]{"workNoticeId",null,"routingId",null,"workCenterId",null,"status","空闲"}));
        json.put("values",JsonUtil.buildJson(new Object[]{"workNoticeId",null,"routingId",null,"workCenterId",null}));
        workUnitService.updateById(json);
        updateWorkUnitStatus(json.getLong("id"),BasicStatus.WORK_UNIT_STATUS_FREE);
    }
}
